/**
 * 朴素版的Prim算法
* 流程：
 * 1.先把所有点到这个集合的距离初始化成正无穷
 * 2. n 次迭代 for(int i = ; i < n ; i++)
 * 3.找到集合外距离这个集合最近的点 t
 * 4.用 t 来更新其他点到集合的距离   st[t] = true
 *
 * 1.先挑一个点作为集合内的点   比如第一个点，用这个点更新其他的点
 * 2.迭代 n 次是因为这里面刚开始是一个点都没选进来的 ， 迪杰斯特拉是因为原本就有一个点在里面 ，只有  n - 1 次
 * 3.正边和负边都可以
*/

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std ;

const int maxn = 510 , INF = 0x3f3f3f3f;  //边和点的数量级一致

int n , m ; //表示边和点的数量

//稠密图用邻接矩阵存
int g[maxn][maxn] ;
int dist[maxn]; //存每个点到这个集合的距离
bool st[maxn];

int Prim() {
    memset(dist , 0x3f , sizeof dist);  //先给所有点的距离初始化为正无穷

    int res = 0 ;   //最小生成树中所有边的长度之和
    for (int i = 0; i < n; ++i) {   //这里只是迭代 n 次，从 0 还是 1 开始无所谓
        //遍历所有点
        int t = -1 ;    //找到不在集合中的最小的点  t == -1 时表示当前还没有找到任何一个点
        for(int j = 1 ; j <= n ; j++){
            if(!st[j] && (t == -1 || dist[t] > dist[j])) {
                t = j ;
            }
        }   //现在 t 存的就是距离最近的一个点

        if( i  && dist[t] == INF) { //i == 0 的时候要单独处理， 因为这时候所有的点都是无穷
            return INF ;
        }

        if(i){
            res += dist[t];
        }
        st[t] = true;

        for(int j = 1 ; j <= n ; j++) {
            dist[j] = min(dist[j] , g[t][j]);
        }

    }
    return res ;
}

int main() {
    scanf("%d%d", &n, &m);
    memset(g, 0x3f, sizeof g);

    while (m--) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = g[b][a] = min(g[a][b], c);   //无向图存两条边
    }

    int t = Prim();

    if (t == INF) {
        puts("impossible");
    }else{
        printf("%d\n" , t);
    }

    return 0 ;
}
